<template>
  <div class="bg-ff">
    <div class="Gantt-header">
      <div class="Gantt-header_flex">
        <div class="Gantt-View_Div">
          <p class="toggle-button Gantt-View_p" @click="GanttView">{{ viewText }}</p>
          <ul v-if="isToggleMenu" class="Gantt-View_opacity toggle-menu">
            <li
              v-for="(item, index) in viewNames"
              :key="index"
              :class="activeClass == index ? 'active' : ''"
              @click="GanttViewId(index, item.name)"
            >
              {{ item.name }}
            </li>
          </ul>
        </div>
      </div>
    </div>
    <div class="Gantt-table_flex">
      <div class="Gantt-table_left">
        <div class="Gantt-table_left_title">
          <div>id</div>
          <div>任务名称</div>
          <div>负责人</div>
        </div>
        <div v-for="(item, index) in taskList" id="taskAryy" :key="index">
          <div class="Gantt-table_left_list">
            <div class="Gantt-table_left_intro">
              <p>{{ item.id }}</p>
            </div>
            <div class="Gantt-table_left_intro">
              <p>{{ item.taskName }}</p>
            </div>
            <div class="Gantt-table_left_intro">
              <p>{{ item.name }}</p>
            </div>
          </div>
        </div>
      </div>
      <div class="Gantt-table_right">
        <div class="Gantt-table_right_rew">
          <div v-if="activeClass == 0" ref="tableYear" class="tableYear">
            <template v-for="(item, index) in MothY">
              <p class="Gantt-table_header" :style="{ width: item.width }">
                {{ item.name }}
              </p>
            </template>
          </div>
          <div v-else="activeClass == 1" ref="tableYear" class="tableYear">
            <template v-for="(item, index) in MothY1">
              <p class="" :style="{ width: item.width }">
                {{ item.name }}
              </p>
            </template>
          </div>
          <div ref="tableDay" class="tableDay">
            <template v-for="(item, index) in getActiveClassData()">
              <p
                :ref="item.isToday ? 'today' : 'null'"
                :class="[item.isToday ? 'today' : '', item.bool ? 'Gantt-table_weekend' : '']"
                :style="{ width: item.width }"
              >
                {{ item.name }}{{ getMonthSuffix(item) }}
              </p>
            </template>
          </div>

          <div id="taskBarAryy">
            <div v-for="(item, index) in taskList" :key="index" class="tableList" :style="tableListStyles">
              <div
                class="tableBar"
                :style="{
                  width: item.offsetwidth,
                  left: item.leftwidth,
                  background: '#' + ((Math.random() * 0x1000000) << 0).toString(16).slice(-6),
                }"
              ></div>
              <p
                class="tableNameintro"
                :style="{
                  left: item.tableNameintroWidth,
                }"
              >
                {{ item.taskName }}
              </p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'APP',
  data() {
    const currentDate = new Date(); //当前日期
    var currentYear = currentDate.getFullYear(); //当前年份
    const yearRange = 1; // 前后1年
    const startDate = currentYear - yearRange; //前1年
    const endDate = currentYear + yearRange; //后1年
    const today = currentDate.getDate(); // 获取今天是几号
    var currentYear = currentDate.getFullYear(); //年
    const currentMonth = currentDate.getMonth(); //月
    const displayedYears = {}; // 用于记录已显示的年份
    return {
      currentDate, //当前日期
      currentYear, //当前年份
      yearRange, // 前后1年
      startDate, //前1年
      endDate, //后1年
      today, // 获取今天是几号
      currentYear, //年
      currentMonth, //月
      displayedYears, // 用于记录已显示的年份
      viewNames: [
        { id: '0', name: '日视图' },
        { id: '1', name: '月视图' },
        { id: '2', name: '季度视图' },
        { id: '3', name: '年度视图' },
      ],
      quarters: ['第一季度', '第二季度', '第三季度', '第四季度'], //季度标识
      Annuals: ['上半年', '下半年'], // 年度标识
      activeClass: 0,
      viewText: '日视图',
      taskList: [
        { id: '1', taskName: '前端页面编写', name: '某某某', startDate: '2023-8-10', dateClosed: '2023-8-12' },
        { id: '2', taskName: '前端页面编写', name: '某某某', startDate: '2023-8-12', dateClosed: '2023-8-15' },
        { id: '3', taskName: '前端页面编写', name: '某某某', startDate: '2023-8-15', dateClosed: '2023-8-18' },
        { id: '4', taskName: '前端页面编写', name: '某某某', startDate: '2023-8-10', dateClosed: '2023-8-25' },
        { id: '5', taskName: '前端页面编写', name: '某某某', startDate: '2023-8-1', dateClosed: '2023-8-25' },
        { id: '6', taskName: '前端页面编写', name: '某某某', startDate: '2023-1-10', dateClosed: '2023-1-25' },
        { id: '7', taskName: '前端页面编写', name: '某某某', startDate: '2023-2-10', dateClosed: '2023-2-25' },
        { id: '8', taskName: '前端页面编写', name: '某某某', startDate: '2023-3-10', dateClosed: '2023-3-25' },
        { id: '9', taskName: '前端页面编写', name: '某某某', startDate: '2023-4-10', dateClosed: '2023-4-25' },
        { id: '10', taskName: '前端页面编写', name: '某某某', startDate: '2023-5-10', dateClosed: '2023-5-25' },
        { id: '11', taskName: '前端页面编写', name: '某某某', startDate: '2023-6-10', dateClosed: '2023-6-25' },
        { id: '12', taskName: '前端页面编写', name: '某某某', startDate: '2023-7-10', dateClosed: '2023-7-25' },
        { id: '13', taskName: '前端页面编写', name: '某某某', startDate: '2023-11-17', dateClosed: '2023-11-25' },
      ],
      isToggleMenu: false,
      dateRange: [],
      MothY: [], //年-月
      MothY1: [], //年
      dayView: [], //日视图
      monthView: [], //月视图
      quarterView: [], //季度视图
      yearView: [], //年度视图
      width: 0,
      newW: 0,
    };
  },
  computed: {
    tableListStyles() {
      return {
        width: this.width + 'px',
        background: `repeating-linear-gradient(to right, #DDDDDD, #DDDDDD 1px, transparent 1px, transparent ${this.newW}px)`,
        'border-bottom': '0px',
        'background-size': `${this.newW}px 100%`,
      };
    },
  },
  created() {
    this.tableTh(0);
  },
  mounted() {
    this.$nextTick(() => {
      this.tableRectangle(this.activeClass);
    });
  },
  updated() {
    this.$nextTick(() => {
      this.tableRectangle(this.activeClass);
    });
  },
  methods: {
    GanttView() {
      this.isToggleMenu = !this.isToggleMenu;
    },
    GanttViewId(index, name) {
      this.activeClass = index;
      this.viewText = name;
      this.generateYears(index);
      this.tableTh(index);
      this.isToggleMenu = false;
    },
    tableTh(id) {
      const dateRange = [];
      if (id == 0) {
        //日试图的年月渲染
        for (let year = this.startDate; year <= this.endDate; year++) {
          for (let month = 0; month < 12; month++) {
            const lastDay = new Date(year, month + 1, 0).getDate();
            for (let day = 1; day <= lastDay; day++) {
              dateRange.push(new Date(year, month, day));
            }
            // 在 .tableYear 中添加年份和月份信息
            const yearMonthStr = year + '-' + (month + 1 < 10 ? '0' : '') + (month + 1);
            const width = lastDay * 40 - 1 + 'px'; // 计算宽度
            this.MothY.push({ name: yearMonthStr, width: width });
          }
        }
        //日试图的日渲染，标出周末以及当前日期深颜色
        for (let i = 0; i < dateRange.length; i++) {
          const currentDate = dateRange[i];
          const dayNumber = currentDate.getDay(); // 获取星期几 (0 = 星期日, 1 = 星期一, ...)
          //计算周末
          const isWeekend = dayNumber === 0 || dayNumber === 6;

          const dayText = currentDate.getDate(); //获取日
          const dayYear = currentDate.getFullYear(); // 获取年份
          const dayMonth = currentDate.getMonth(); // 获取月份（注意：月份是从 0 到 11，0 表示一月，11 表示十二月）
          //获取当前日期进行匹配
          const isToday = dayText === this.today && dayYear === this.currentYear && dayMonth === this.currentMonth;
          this.dayView.push({ name: currentDate.getDate(), bool: isWeekend, isToday: isToday });
        }
        //计算任务的宽度 开始时间的位置和结束时间的位置
        for (let j = 0; j < this.taskList.length; j++) {
          const ls = this.taskList[j];
          const offsetDays = this.getOffsetDays(ls.startDate, ls.dateClosed);
          const leftDays = this.getOffsetDays(ls.startDate, this.startDate + '-' + 1 + '-' + 1);
          //console.log(offsetDays)
          const offsetwidth = offsetDays * 40 + 'px';
          const leftwidth = Math.abs(leftDays * 40) + 'px';
          const tableNameintroWidth = Math.abs(leftDays * 40) + offsetDays * 40 + 40 + 'px';
          //向数组中添加新字段
          ls.offsetwidth = offsetwidth;
          ls.leftwidth = leftwidth;
          ls.tableNameintroWidth = tableNameintroWidth;
        }
        this.$nextTick(() => {
          this.tableRectangle(this.activeClass); // 传入实际的 id 值
        });
      }
    },
    //计算任务开始日期和结束日期相差的天数
    getOffsetDays(startDate, endDate) {
      const startDateArr = startDate.split('-');
      const checkStartDate = new Date();
      checkStartDate.setFullYear(startDateArr[0], startDateArr[1] - 1, startDateArr[2]);
      const endDateArr = endDate.split('-');
      const checkEndDate = new Date();
      checkEndDate.setFullYear(endDateArr[0], endDateArr[1] - 1, endDateArr[2]);
      const days = (checkEndDate.getTime() - checkStartDate.getTime()) / (3600000 * 24);
      return days;
    },
    tableRectangle(id) {
      this.width = this.$refs.tableDay.offsetWidth;
      const todayElement = this.$refs.today;
      //将屏幕滚到视口位置
      if (todayElement.length > 0) {
        todayElement[0].scrollIntoView({ behavior: 'auto', block: 'center', inline: 'center' });
      }
      this.newW = id == 0 ? 40 : 201;
    },
    //视图切换
    generateYears(id) {
      this.displayedYears = {}; //清空记录显示的年份
      this.MothY1 = [];
      this.monthView = [];
      this.quarterView = [];
      this.yearView = [];
      for (let year = this.startDate; year <= this.endDate; year++) {
        let newLength = '';
        const quarterElement = '';
        let newwidth = '';
        if (id == 1) {
          newLength = 12;
          newwidth = 12 * 201 - 1 + 'px';
        } else if (id == 2) {
          newLength = 4;
          newwidth = 4 * 201 - 1 + 'px';
        } else if (id == 3) {
          newLength = 2;
          newwidth = 2 * 201 - 1 + 'px';
        }
        for (let quarterIndex = 0; quarterIndex < newLength; quarterIndex++) {
          const width = 200 + 'px'; // 计算宽度

          if (!this.displayedYears[year]) {
            this.MothY1.push({ name: year, width: newwidth });
            this.displayedYears[year] = true; // 记录已显示的年份
          }
          if (id == 1) {
            var isToday = year === this.currentYear && quarterIndex === this.currentMonth;
            this.monthView.push({
              name: quarterIndex + 1,
              width: width,
              isToday: isToday,
            });
          } else if (id == 2) {
            var currentQuarter;
            if (this.currentMonth >= 1 && this.currentMonth <= 3) {
              currentQuarter = 1;
            } else if (this.currentMonth >= 4 && this.currentMonth <= 6) {
              currentQuarter = 2;
            } else if (this.currentMonth >= 7 && this.currentMonth <= 9) {
              currentQuarter = 3;
            } else {
              currentQuarter = 4;
            }
            var isToday = year === this.currentYear && quarterIndex + 1 === currentQuarter;
            this.quarterView.push({
              name: this.quarters[quarterIndex],
              width: width,
              isToday: isToday,
            });
          } else {
            var currentQuarter;
            if (this.currentMonth >= 1 && this.currentMonth <= 6) {
              currentQuarter = 1;
            } else {
              currentQuarter = 2;
            }
            var isToday = year === this.currentYear && quarterIndex + 1 === currentQuarter;

            this.yearView.push({
              name: this.Annuals[quarterIndex],
              width: width,
              isToday: isToday,
            });
          }
        }
      }
      for (let j = 0; j < this.taskList.length; j++) {
        const ls = this.taskList[j];
        const offsetDays = this.getOffsetDays(ls.startDate, ls.dateClosed);
        const leftDays = this.getOffsetDays(ls.startDate, this.startDate + '-' + 1 + '-' + 1);

        //向数组中添加新字段
        if (id == 1) {
          ls.offsetwidth = (offsetDays * 200) / 30 + 'px';
          ls.leftwidth = Math.abs(leftDays * 200) / 30 + 'px';
          ls.tableNameintroWidth = Math.abs(leftDays * 200) / 30 + (offsetDays * 200) / 30 + 40 + 'px';
        } else if (id == 2) {
          ls.offsetwidth = (offsetDays * 200) / 90 + 'px';
          ls.leftwidth = Math.abs(leftDays * 200) / 90 + 'px';
          ls.tableNameintroWidth = Math.abs(leftDays * 200) / 90 + (offsetDays * 200) / 90 + 40 + 'px';
        } else if (id == 3) {
          ls.offsetwidth = (offsetDays * 200) / 180 + 'px';
          ls.leftwidth = Math.abs(leftDays * 200) / 180 + 'px';
          ls.tableNameintroWidth = Math.abs(leftDays * 200) / 180 + (offsetDays * 200) / 180 + 40 + 'px';
        }
      }

      this.tableRectangle(id);
    },
    getActiveClassData() {
      switch (this.activeClass) {
        case 0:
          return this.dayView;
        case 1:
          return this.monthView;
        case 2:
          return this.quarterView;
        case 3:
          return this.yearView;
        default:
          return [];
      }
    },
    getMonthSuffix(item) {
      if (this.activeClass === 1) {
        return ' 月';
      }
      return '';
    },
  },
};
</script>

<style>
body,
table,
th,
td,
p,
ul {
  padding: 0px;
  margin: 0px;
}

a {
  text-decoration: none;
}

button::after,
button::before {
  border: none;
}

button {
  background: none;
  border: none;
}

button:focus {
  outline: none;
}

table {
  border-collapse: collapse;
  width: 100%;
}

table tr th,
table tr td {
  border: 1px solid #dddddd;
  padding: 10px;
}

table tr th {
  font-size: 18px;
}

table tr td {
  font-size: 15px;
}

ol li,
ul li {
  list-style: none;
}

.Gantt-header {
  padding: 20px;
}

.Gantt-header_flex {
  display: flex;
  align-items: center;
}

.Gantt-View_Div {
  background-color: #609;
  color: #fff;
  border-radius: 8px;
  position: relative;
}

.Gantt-View_Div:hover {
  cursor: pointer;
}

.Gantt-View_Div p {
  display: flex;
  font-size: 16px;
  padding: 5px 25px;
}

.Gantt-View_Div p i {
  font-size: 22px;
}

.Gantt-View_opacity {
  position: absolute;
  background: #ffffff;
  width: 100%;
  min-width: 100px;
  border-radius: 3px 3px 3px 3px;
  padding: 10px;
  box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.09);
}

.Gantt-View_opacity li {
  font-size: 14px;
  color: #333333;
  display: block;
  padding: 5px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.Gantt-View_opacity li.active i {
  display: block;
}

.Gantt-View_opacity li i {
  display: none;
}

.Gantt-View_opacity li i {
  font-size: 22px;
}

.Gantt-View_opacity li:hover {
  background: #660099;
  color: #ffffff;
  cursor: pointer;
}

.Gantt-table_flex {
  display: flex;
}

.Gantt-table_left {
  width: 20%;
}

.Gantt-table_left_title,
.Gantt-table_left_list {
  display: flex;
  justify-content: space-between;
  height: 40px;
}

.Gantt-table_left_title {
  height: 79px;
}

.Gantt-table_left_title div,
.Gantt-table_left_list div {
  width: 33%;
  text-align: center;
  border: 1px solid #dddddd;
  display: flex;
  justify-content: center;
  align-items: center;
  border-right: 0px;
}

.Gantt-table_left_title div:last-of-type,
.Gantt-table_left_list div:last-of-type {
  border-right: 1px solid #dddddd;
}

.Gantt-table_left_title,
.Gantt-table_left_title div,
.Gantt-table_left_list div {
  border-bottom: 0px;
}

.Gantt-table_left_title:last-of-type {
  border-bottom: 1px solid #dddddd;
}

.Gantt-table_left_intro p {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: block;
  -o-text-overflow: ellipsis;
  line-height: 40px;
  padding: 0px 10px;
}

.Gantt-table_right {
  width: 80%;
}
.tableYear {
  text-align: left;
}
.Gantt-table_right .tableDay,
.Gantt-table_right .tableYear,
.Gantt-table_right {
  display: inline-flex;
}

.Gantt-table_right .tableDay p,
.Gantt-table_right .tableList .Gantt-table_header {
  line-height: 38px;
  width: 39px;
  height: 38px;
}

.Gantt-table_right .tableDay p,
.Gantt-table_right .tableYear p,
.Gantt-table_right .tableList .Gantt-table_header {
  border: 1px solid #dddddd;
  border-right: 0px;
  text-align: center;
}

.Gantt-table_right .tableYear p {
  border-bottom: 0px;
  line-height: 39px;
  height: 39px;
}

.Gantt-table_right .tableList .Gantt-table_header {
  border-top: 0px;
}

.Gantt-table_right .tableDay p:nth-child(1),
.Gantt-table_right .tableYear p:nth-child(1),
.Gantt-table_right .tableList p:nth-child(1) {
  border-left: 0px;
}

.Gantt-table_right .tableDay p:last-of-type,
.Gantt-table_right .tableYear p:last-of-type,
.Gantt-table_right .tableList:last-of-type {
  border-right: 1px solid #dddddd;
}

.Gantt-table_right_rew {
  width: 1500px;
  overflow-x: scroll;
  text-align: left;
}

.Gantt-table_weekend {
  background-color: #eeeeee;
}

.Gantt-table_right .today {
  background-color: #660099;
  color: #ffffff;
}

/* .tableList{width: 1500px;height: 40px;position: relative; background-color: white;} */
.tableList {
  width: 1200px;
  height: 40px;
  border: 1px solid #dddddd;
  border-left: 0px;
  border-top: 0px;
  margin-left: -1px;
  position: relative;
  display: flex;
  align-items: center;
}

.tableList:hover {
  cursor: pointer;
  background-color: #eeeeee;
}

.tableBar {
  background: red;
  width: 200px;
  height: 15px;
  top: 15px;
  position: absolute;
  border-radius: 10px;
  left: 200px;
}

.tableNameintro {
  white-space: nowrap;
  position: absolute;
}

.tableBar:hover {
  border-radius: 0px;
}
</style>
